/***************************************************************************
 *   Copyright (C) 2008 by BogDan Vatra                                    *
 *   bogdan@licentia.eu                                                    *
 *                                                                         *
 *   This program is free software: you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation, either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
 ***************************************************************************/

#include <QAction>
#include <QApplication>
#include <QClipboard>
#include <QColorDialog>
#include <QComboBox>
#include <QFontComboBox>
#include <QFile>
#include <QFileDialog>
#include <QFileInfo>
#include <QFontDatabase>
#include <QMenu>
#include <QMenuBar>
#include <QPrintDialog>
#include <QPrinter>
#include <QTextCodec>
#include <QToolBar>
#include <QTextCursor>
#include <QTextList>
#include <QtDebug>
#include <QCloseEvent>
#include <QMessageBox>
#include <QPrintPreviewDialog>
#include <QHBoxLayout>

#include "textedit.h"

#include "textedittoolbar.h"


const QString rsrcPath = ":/textedittoolbar/images";

inline void initMyResource()
{
	Q_INIT_RESOURCE(kontAMabil);
}

TextEditToolBar::TextEditToolBar(QWidget *parent)
		: QWidget(parent), m_textEdit(0)
{
	initMyResource();
	setEnabled(false);
	m_verticalLayout= new QVBoxLayout(this);
	m_horizontalLayout = new QHBoxLayout;
	m_verticalLayout->addLayout(m_horizontalLayout);
	setupEditActions();
	setupTextActions();
}



QString TextEditToolBar::textEditName()
{
	return m_textEditName;
}

void TextEditToolBar::setTextEditName(const QString & textEditName)
{
	setEnabled(false);
	m_textEditName=textEditName;
}

void TextEditToolBar::showEvent ( QShowEvent * event )
{
	QWidget::showEvent (event);
	if (m_textEdit || !m_textEditName.length())
		return;

	if (parent() && parent()->findChildren<QTextEdit*>(m_textEditName).size())
		m_textEdit=parent()->findChildren<QTextEdit*>(m_textEditName)[0];

	if (!m_textEdit)
		return;

	setEnabled(true);
	m_comboStyle->setEnabled(true);
	m_comboFont->setEnabled(true);
	m_comboSize->setEnabled(true);

	connect(m_textEdit, SIGNAL(currentCharFormatChanged(const QTextCharFormat &)),
	        this, SLOT(currentCharFormatChanged(const QTextCharFormat &)));

	connect(m_textEdit, SIGNAL(cursorPositionChanged()),
	        this, SLOT(cursorPositionChanged()));

	fontChanged(m_textEdit->font());
	colorChanged(m_textEdit->textColor());
	alignmentChanged(m_textEdit->alignment());

	connect(m_textEdit->document(), SIGNAL(modificationChanged(bool)),
	        this, SLOT(setWindowModified(bool)));
	connect(m_textEdit->document(), SIGNAL(undoAvailable(bool)),
	        m_actionUndo, SLOT(setEnabled(bool)));
	connect(m_textEdit->document(), SIGNAL(redoAvailable(bool)),
	        m_actionRedo, SLOT(setEnabled(bool)));

	setWindowModified(m_textEdit->document()->isModified());
	m_actionUndo->setEnabled(m_textEdit->document()->isUndoAvailable());
	m_actionRedo->setEnabled(m_textEdit->document()->isRedoAvailable());

	connect(m_actionUndo, SIGNAL(triggered()), m_textEdit, SLOT(undo()));
	connect(m_actionRedo, SIGNAL(triggered()), m_textEdit, SLOT(redo()));

	m_actionCut->setEnabled(false);
	m_actionCopy->setEnabled(false);

	connect(m_actionCut, SIGNAL(triggered()), m_textEdit, SLOT(cut()));
	connect(m_actionCopy, SIGNAL(triggered()), m_textEdit, SLOT(copy()));
	connect(m_actionPaste, SIGNAL(triggered()), m_textEdit, SLOT(paste()));

	connect(m_textEdit, SIGNAL(copyAvailable(bool)), m_actionCut, SLOT(setEnabled(bool)));
	connect(m_textEdit, SIGNAL(copyAvailable(bool)), m_actionCopy, SLOT(setEnabled(bool)));

	connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clipboardDataChanged()));

}

void TextEditToolBar::setupEditActions()
{
	QToolBar *tb = new QToolBar(this);
	tb->setWindowTitle(tr("Edit Actions"));
	m_horizontalLayout->addWidget(tb);

	QAction *a;
	a = m_actionUndo = new QAction(QIcon(rsrcPath + "/editundo.png"), tr("&Undo"), this);
	a->setShortcut(QKeySequence::Undo);
	tb->addAction(a);
	a = m_actionRedo = new QAction(QIcon(rsrcPath + "/editredo.png"), tr("&Redo"), this);
	a->setShortcut(QKeySequence::Redo);
	tb->addAction(a);
	a = m_actionCut = new QAction(QIcon(rsrcPath + "/editcut.png"), tr("Cu&t"), this);
	a->setShortcut(QKeySequence::Cut);
	tb->addAction(a);
	a = m_actionCopy = new QAction(QIcon(rsrcPath + "/editcopy.png"), tr("&Copy"), this);
	a->setShortcut(QKeySequence::Copy);
	tb->addAction(a);
	a = m_actionPaste = new QAction(QIcon(rsrcPath + "/editpaste.png"), tr("&Paste"), this);
	a->setShortcut(QKeySequence::Paste);
	tb->addAction(a);
	m_actionPaste->setEnabled(!QApplication::clipboard()->text().isEmpty());
}

void TextEditToolBar::setupTextActions()
{
	QToolBar *tb = new QToolBar(this);
	tb->setWindowTitle(tr("Format Actions"));
	m_horizontalLayout->addWidget(tb);

	m_actionTextBold = new QAction(QIcon(rsrcPath + "/textbold.png"), tr("&Bold"), this);
	m_actionTextBold->setShortcut(Qt::CTRL + Qt::Key_B);
	QFont bold;
	bold.setBold(true);
	m_actionTextBold->setFont(bold);
	connect(m_actionTextBold, SIGNAL(triggered()), this, SLOT(textBold()));
	tb->addAction(m_actionTextBold);
	m_actionTextBold->setCheckable(true);

	m_actionTextItalic = new QAction(QIcon(rsrcPath + "/textitalic.png"), tr("&Italic"), this);
	m_actionTextItalic->setShortcut(Qt::CTRL + Qt::Key_I);
	QFont italic;
	italic.setItalic(true);
	m_actionTextItalic->setFont(italic);
	connect(m_actionTextItalic, SIGNAL(triggered()), this, SLOT(textItalic()));
	tb->addAction(m_actionTextItalic);
	m_actionTextItalic->setCheckable(true);

	m_actionTextUnderline = new QAction(QIcon(rsrcPath + "/textunder.png"), tr("&Underline"), this);
	m_actionTextUnderline->setShortcut(Qt::CTRL + Qt::Key_U);
	QFont underline;
	underline.setUnderline(true);
	m_actionTextUnderline->setFont(underline);
	connect(m_actionTextUnderline, SIGNAL(triggered()), this, SLOT(textUnderline()));
	tb->addAction(m_actionTextUnderline);
	m_actionTextUnderline->setCheckable(true);

	QActionGroup *grp = new QActionGroup(this);
	connect(grp, SIGNAL(triggered(QAction *)), this, SLOT(textAlign(QAction *)));

	m_actionAlignLeft = new QAction(QIcon(rsrcPath + "/textleft.png"), tr("&Left"), grp);
	m_actionAlignLeft->setShortcut(Qt::CTRL + Qt::Key_L);
	m_actionAlignLeft->setCheckable(true);
	m_actionAlignCenter = new QAction(QIcon(rsrcPath + "/textcenter.png"), tr("C&enter"), grp);
	m_actionAlignCenter->setShortcut(Qt::CTRL + Qt::Key_E);
	m_actionAlignCenter->setCheckable(true);
	m_actionAlignRight = new QAction(QIcon(rsrcPath + "/textright.png"), tr("&Right"), grp);
	m_actionAlignRight->setShortcut(Qt::CTRL + Qt::Key_R);
	m_actionAlignRight->setCheckable(true);
	m_actionAlignJustify = new QAction(QIcon(rsrcPath + "/textjustify.png"), tr("&Justify"), grp);
	m_actionAlignJustify->setShortcut(Qt::CTRL + Qt::Key_J);
	m_actionAlignJustify->setCheckable(true);

	tb->addActions(grp->actions());

	QPixmap pix(16, 16);
	pix.fill(Qt::black);
	m_actionTextColor = new QAction(pix, tr("&Color..."), this);
	connect(m_actionTextColor, SIGNAL(triggered()), this, SLOT(textColor()));
	tb->addAction(m_actionTextColor);


	tb = new QToolBar(this);
	tb->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea);
	tb->setWindowTitle(tr("Format Actions"));
	m_verticalLayout->addWidget(tb);
	m_comboStyle = new QComboBox(tb);
	tb->addWidget(m_comboStyle);
	m_comboStyle->addItem("Standard");
	m_comboStyle->addItem("Bullet List (Disc)");
	m_comboStyle->addItem("Bullet List (Circle)");
	m_comboStyle->addItem("Bullet List (Square)");
	m_comboStyle->addItem("Ordered List (Decimal)");
	m_comboStyle->addItem("Ordered List (Alpha lower)");
	m_comboStyle->addItem("Ordered List (Alpha upper)");
	connect(m_comboStyle, SIGNAL(activated(int)),
	        this, SLOT(textStyle(int)));

	m_comboFont = new QFontComboBox(tb);
	tb->addWidget(m_comboFont);
	connect(m_comboFont, SIGNAL(activated(const QString &)),
	        this, SLOT(textFamily(const QString &)));

	m_comboSize = new QComboBox(tb);
	m_comboSize->setObjectName("comboSize");
	tb->addWidget(m_comboSize);
	m_comboSize->setEditable(true);

	QFontDatabase db;
	foreach(int size, db.standardSizes())
	m_comboSize->addItem(QString::number(size));

	connect(m_comboSize, SIGNAL(activated(const QString &)),
	        this, SLOT(textSize(const QString &)));
	m_comboSize->setCurrentIndex(m_comboSize->findText(QString::number(QApplication::font()
	                           .pointSize())));
}


void TextEditToolBar::textBold()
{
	QTextCharFormat fmt;
	fmt.setFontWeight(m_actionTextBold->isChecked() ? QFont::Bold : QFont::Normal);
	mergeFormatOnWordOrSelection(fmt);
}

void TextEditToolBar::textUnderline()
{
	QTextCharFormat fmt;
	fmt.setFontUnderline(m_actionTextUnderline->isChecked());
	mergeFormatOnWordOrSelection(fmt);
}

void TextEditToolBar::textItalic()
{
	QTextCharFormat fmt;
	fmt.setFontItalic(m_actionTextItalic->isChecked());
	mergeFormatOnWordOrSelection(fmt);
}

void TextEditToolBar::textFamily(const QString &f)
{
	QTextCharFormat fmt;
	fmt.setFontFamily(f);
	mergeFormatOnWordOrSelection(fmt);
}

void TextEditToolBar::textSize(const QString &p)
{
	QTextCharFormat fmt;
	fmt.setFontPointSize(p.toFloat());
	mergeFormatOnWordOrSelection(fmt);
}

void TextEditToolBar::textStyle(int styleIndex)
{
	QTextCursor cursor = m_textEdit->textCursor();

	if (styleIndex != 0)
	{
		QTextListFormat::Style style = QTextListFormat::ListDisc;

		switch (styleIndex)
		{
			default:
			case 1:
				style = QTextListFormat::ListDisc;
				break;
			case 2:
				style = QTextListFormat::ListCircle;
				break;
			case 3:
				style = QTextListFormat::ListSquare;
				break;
			case 4:
				style = QTextListFormat::ListDecimal;
				break;
			case 5:
				style = QTextListFormat::ListLowerAlpha;
				break;
			case 6:
				style = QTextListFormat::ListUpperAlpha;
				break;
		}

		cursor.beginEditBlock();

		QTextBlockFormat blockFmt = cursor.blockFormat();

		QTextListFormat listFmt;

		if (cursor.currentList())
		{
			listFmt = cursor.currentList()->format();
		}
		else
		{
			listFmt.setIndent(blockFmt.indent() + 1);
			blockFmt.setIndent(0);
			cursor.setBlockFormat(blockFmt);
		}

		listFmt.setStyle(style);

		cursor.createList(listFmt);

		cursor.endEditBlock();
	}
	else
	{
		// ####
		QTextBlockFormat bfmt;
		bfmt.setObjectIndex(-1);
		cursor.mergeBlockFormat(bfmt);
	}
}

void TextEditToolBar::textColor()
{
	if (!m_textEdit)
		return;
	QColor col = QColorDialog::getColor(m_textEdit->textColor(), this);
	if (!col.isValid())
		return;
	QTextCharFormat fmt;
	fmt.setForeground(col);
	mergeFormatOnWordOrSelection(fmt);
	colorChanged(col);
}

void TextEditToolBar::textAlign(QAction *a)
{
	if (!m_textEdit)
		return;
	if (a == m_actionAlignLeft)
		m_textEdit->setAlignment(Qt::AlignLeft);
	else
		if (a == m_actionAlignCenter)
			m_textEdit->setAlignment(Qt::AlignHCenter);
		else
			if (a == m_actionAlignRight)
				m_textEdit->setAlignment(Qt::AlignRight);
			else
				if (a == m_actionAlignJustify)
					m_textEdit->setAlignment(Qt::AlignJustify);
}

void TextEditToolBar::currentCharFormatChanged(const QTextCharFormat &format)
{
	fontChanged(format.font());
	colorChanged(format.foreground().color());
}

void TextEditToolBar::cursorPositionChanged()
{
	if (!m_textEdit)
		return;
	alignmentChanged(m_textEdit->alignment());
}

void TextEditToolBar::clipboardDataChanged()
{
	m_actionPaste->setEnabled(!QApplication::clipboard()->text().isEmpty());
}

void TextEditToolBar::mergeFormatOnWordOrSelection(const QTextCharFormat &format)
{
	if (!m_textEdit)
		return;
	QTextCursor cursor = m_textEdit->textCursor();
	if (!cursor.hasSelection())
		cursor.select(QTextCursor::WordUnderCursor);
	cursor.mergeCharFormat(format);
	m_textEdit->mergeCurrentCharFormat(format);
}

void TextEditToolBar::fontChanged(const QFont &f)
{
	m_comboFont->setCurrentIndex(m_comboFont->findText(QFontInfo(f).family()));
	m_comboSize->setCurrentIndex(m_comboSize->findText(QString::number(f.pointSize())));
	m_actionTextBold->setChecked(f.bold());
	m_actionTextItalic->setChecked(f.italic());
	m_actionTextUnderline->setChecked(f.underline());
}

void TextEditToolBar::colorChanged(const QColor &c)
{
	QPixmap pix(16, 16);
	pix.fill(c);
	m_actionTextColor->setIcon(pix);
}

void TextEditToolBar::alignmentChanged(Qt::Alignment a)
{
	if (a & Qt::AlignLeft)
	{
		m_actionAlignLeft->setChecked(true);
	}
	else
		if (a & Qt::AlignHCenter)
		{
			m_actionAlignCenter->setChecked(true);
		}
		else
			if (a & Qt::AlignRight)
			{
				m_actionAlignRight->setChecked(true);
			}
			else
				if (a & Qt::AlignJustify)
				{
					m_actionAlignJustify->setChecked(true);
				}
}

